using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using System.Configuration;

namespace Commonplace.Controller
{
	/// <summary>
	/// Checks for new versions and automatically downloads new updates
	/// </summary>
	public class AutoUpdate
	{
		static string _autoupdateCheckLocation = "http://www.tiredbrain.com/wikimedia/commonplace/version/";
		const string _ApplicationName = "Wikimedia Commonplace";

		Version _currentVersion;
		Version _newVersion;
		
		XmlElement _message = null;

		string _newUrl = string.Empty;
		DownloadRunner _downloader = null;
		string _fullPath;

        static AutoUpdate()
        {
            _autoupdateCheckLocation = ConfigurationManager.AppSettings["Autoupdate.URL"];
        }

		public AutoUpdate()
		{
			_currentVersion = new Version(FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileVersion);
		}

		/// <summary>
		/// Checks if the web server is returning a 
		/// </summary>
		/// <returns>True if the current version is older than the published version number, false otherwise</returns>
		private bool NewVersionExists()
		{
			WebClient wc = new WebClient();
			Stream newVersionStream = wc.OpenRead(_autoupdateCheckLocation);
			XmlDocument doc = new XmlDocument();
			doc.Load(newVersionStream);
			newVersionStream.Close();

			_message = doc.SelectSingleNode("//message") as XmlElement;
			XmlElement versionNode = doc.SelectSingleNode("//current") as XmlElement;
			_newVersion = new Version(versionNode.GetAttribute("version"));
			if (_newVersion > _currentVersion)
			{
				_newUrl = versionNode.GetAttribute("url");
				return true;
			}

			return false;
		}

		/// <summary>
		/// Asks the user if they would like to download and install the new vesion
		/// </summary>
		/// <returns>True if the user agrees, false otherwise</returns>
		private bool ConfirmDesireToUpdate()
		{
			string additionalMessage = "";

			if (null != _message)
			{
				additionalMessage += "\r\n\r\nThe new version advertises the following changes:\r\n\r\n";
				foreach (XmlNode node in _message.ChildNodes)
				{
					if (node is XmlText)
						additionalMessage += node.Value.Trim() + "\r\n";
					else if (node is XmlElement && node.Name == "br")
						additionalMessage += "\r\n";
					else if (node is XmlElement && node.Name == "li")
						additionalMessage += string.Format(" - {0}\r\n", node.InnerText.Trim());
				}
			}

			DialogResult res = MessageBox.Show(
				string.Format("A new version ({0}) of this application is available.\r\nWould you like to download and install the update now?{1}", _newVersion.ToString(), additionalMessage), 
				_ApplicationName, 
				MessageBoxButtons.YesNo, 
				MessageBoxIcon.Question);

			if (DialogResult.Yes == res)
				return true;

			return false;
		}
			

		/// <summary>
		/// Initiates the process of checking version numbers and downloading updates
		/// </summary>
		public void GetNewFile()
		{
			_downloader = new DownloadRunner(DoDownload);
			_downloader.BeginInvoke(new AsyncCallback(DownloadComplete), null);
		}

		private void DownloadComplete(IAsyncResult result)
		{
			bool status = _downloader.EndInvoke(result);
			if (true == status)
				MessageBox.Show(string.Format("The new version has been downloaded to your desktop into a file named {0}.\nUninstall the current version of Wikimedia Commonplace and install the downloaded version.", _fullPath), _ApplicationName, MessageBoxButtons.OK, MessageBoxIcon.Information);
		}

		private bool DoDownload()
		{
			//delay for a few seconds -- currently 2 seconds
			Thread.Sleep(2000);

			try
			{
				if (true == NewVersionExists())
				{
					if (true == ConfirmDesireToUpdate())
					{
						WebClient wc = new WebClient();
						UriBuilder u = new UriBuilder(_newUrl);
					
						string filename = u.Path.Substring(u.Path.LastIndexOf('/'));
						if (filename.Length <= 1)
							return false;

						filename = string.Format("{0}_{1}",_newVersion, filename.Remove(0,1));
						string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
						string currentDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
						_fullPath = Path.Combine(desktopPath, filename);
						//MessageBox.Show(_fullPath);

						wc.DownloadFile(_newUrl, _fullPath);
					
						return true;

					}
				}
			}
			catch
			{
				//no big deal if we can't check the autoupdate at runtime
			}
			

			return false;
		}

        
        private delegate bool DownloadRunner();
		
	}
}
